#pragma once

#include "sock.hpp"
#include <sys/epoll.h>
#include <unordered_map>

#define SIZE 256
#define NUM 64

namespace ns_epoll
{
  class Epoller;
  class EventItem;
  // 函数指针，回调机制
  typedef int (*callback_t)(EventItem*);
  struct Peer
  {
    std::string _ip;
    uint16_t _port;
    Peer(std::string ip = "", uint16_t port = 0)
      :_ip(ip)
       ,_port(port)
    {}
    Peer(const Peer& peer)
    {
      _ip = peer._ip;
      _port = peer._port;
    }
  };
  // 用来描述事件 各个项
  class EventItem
  {
  public:
    // 用于注册回调
    void ManagerCallBack(callback_t recv_handler, callback_t send_handler, callback_t error_handler)
    {
      _recv_handler = recv_handler;
      _send_handler = send_handler;
      _error_handler = error_handler;
    }
  public:
    int _sock = -1;// 用于通信的套接字（监听套接字和普通套接字）
    Epoller* _R = nullptr;// 回指，指向受托管于哪个事件管理器

    // 回调机制
    callback_t _recv_handler = nullptr;// 读回调机制
    callback_t _send_handler = nullptr;// 发送回调机制
    callback_t _error_handler = nullptr;// 错误回调机制
    
    // 两个缓冲区
    std::string _inbuffer;// 接受缓冲区，存储接受到的数据，待交付
    std::string _outbuffer;// 发送缓冲区，存储待发送的数据
  };
  // 事件管理器
  class Epoller
  {
  public:
    void InitEpoller()
    {
      // 创建epoll模型
      _epfd = epoll_create(SIZE); 
      if (_epfd < 0){
        std::cerr << "create epoll error" << std::endl;
        exit(4);
      }
    }
    // 事件分配器
    void Dispatcher(int timeout)
    {
      struct epoll_event revs[NUM];
      int num = epoll_wait(_epfd, revs, NUM, timeout);
      for (int i = 0; i < num; ++i)
      {
        int sock = revs[i].data.fd;
        if (revs[i].events&EPOLLIN)
          if (_event_items[sock]._recv_handler) _event_items[sock]._recv_handler(&_event_items[sock]);
        if (revs[i].events&EPOLLOUT)
          if (_event_items[sock]._send_handler) _event_items[sock]._send_handler(&_event_items[sock]);
        if (revs[i].events&EPOLLERR)
          if (_event_items[sock]._error_handler) _event_items[sock]._error_handler(&_event_items[sock]);
      }
    }
    void AddEvents(int fd, const EventItem& item, uint32_t events)
    {
      struct epoll_event ev;
      
      ev.events = 0;
      ev.events |= events;
      ev.data.fd = fd;// 方便后序知道是哪一个文件描述符就绪

      if (epoll_ctl(_epfd, EPOLL_CTL_ADD, fd, &ev) < 0){
        std::cerr << "epoll_ctl add-error" << std::endl;
      }
      // 把事件添加到哈希表中
      _event_items.insert({fd, item});
    }
    void DeLEvents(int fd)
    {
      if (epoll_ctl(_epfd, EPOLL_CTL_DEL, fd, nullptr) < 0){
        std::cerr << "epoll_ctl del-error, fd:" << fd << std::endl;
      }
      // 去掉哈希表中相关fd
      _event_items.erase(fd);
    }
    void EnableReadWrite(int sock, bool read, bool write)
    {
      struct epoll_event ev;
      ev.data.fd = sock;
      ev.events = (read ? EPOLLIN : 0)| (write ? EPOLLOUT : 0) | EPOLLET;
      if (epoll_ctl(_epfd, EPOLL_CTL_MOD, sock, &ev)<0){
        std::cerr << "epoll_ctl enable-error, fd: " << sock << std::endl;
      }
    }
    ~Epoller()
    {
      if (_epfd>=0) close(_epfd);
    }
  private:
    int _epfd = -1;
    std::unordered_map<int, EventItem> _event_items;// 记录事件与套接字的映射关系
  public:
    std::unordered_map<int, Peer> _sock_peer;
  };
}
